package com.ldr.custom.spring.v3.webmvc;

import com.alibaba.fastjson.JSONObject;
import com.ldr.custom.spring.factory.ConvertFactory;
import com.ldr.custom.spring.strategy.ConvertStrategy;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

//专人做专事，解偶
public class GPHandlerAdapter {

    private Map<String, Integer> paramMapping;

    public GPHandlerAdapter(Map<String, Integer> paramMapping) {
        this.paramMapping = paramMapping;
    }

    public boolean support(Object obj) {
        return obj instanceof GPHandlerAdapter;
    }

    /**
     * 为什么传handler，因为参数包含controller，method，url信息
     *
     * @param req
     * @param resp
     * @param handler
     * @return
     */
    public GPModelAndView handle(HttpServletRequest req, HttpServletResponse resp, GPHandlerMapping handler) throws InvocationTargetException, IllegalAccessException, InstantiationException, IOException {
        //根据用户请求的参数信息，跟method中的参数信息进行动态匹配

        //resp传进来的目的只有一个，只是为了将其赋值给方法参数，仅此而已

        //只有当用户传过来的ModelAndView为空的时候，才会new一个

        //1、要准备好这个方法的形参列表
        //方法重载：形参的决定因素，参数个数，参数类型，参数顺序，方法名字
        Class<?>[] parameterTypes = handler.getParameterTypes();


        Object[] paramValues = new Object[parameterTypes.length];
        Integer index = null;

        if ("GET".equals(req.getMethod())) {


            //2、拿到自定义的命名参数所在的位置

            Map<String, String[]> parameterMap = req.getParameterMap();
            //3、构造实参列表
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                index = this.paramMapping.get(entry.getKey());
                if (index != null) {

                    //创建转换工厂模式
                    ConvertStrategy convertStrategy = ConvertFactory.getInstance().getConvertStrategy(parameterTypes[index]);
                    String[] values = entry.getValue();
                    if (values.length > 1) {
                        paramValues[index] = convertStrategy.convert(values);
                    } else if (values.length == 1) {
                        paramValues[index] = convertStrategy.convert(values[0]);
                    }
                }

            }
        } else {
            for (Map.Entry<String, Integer> paramMapping : this.paramMapping.entrySet()) {

                Object attribute = req.getParameter(paramMapping.getKey());

                if (attribute != null) {
                    index = paramMapping.getValue();
                    //创建转换工厂模式
                    ConvertStrategy convertStrategy = ConvertFactory.getInstance().getConvertStrategy(parameterTypes[index]);

                    paramValues[index] = convertStrategy.convert(attribute);
                }
            }
        }

        Integer reqIndex = this.paramMapping.get(HttpServletRequest.class.getSimpleName());
        if (reqIndex != null) {
            paramValues[reqIndex] = req;
        }

        Integer respIndex = this.paramMapping.get(HttpServletResponse.class.getSimpleName());
        if (respIndex != null) {
            paramValues[respIndex] = resp;
        }


        //4、从handler中取出controller，method，然后利用反射机制调用
        Object obj = handler.getMethod().invoke(handler.getController(), paramValues);
        if (obj == null) {
            return null;
        }
        if (obj instanceof GPModelAndView) {
            return (GPModelAndView) obj;
        } else {
            resp.getWriter().write(JSONObject.toJSONString(obj));
            return null;
        }
    }
}
